#include "stdafx.h"
#include "url_ip_rule.h"
#include <semaphore.h>
#include "../lib/lib.h"
#include <time.h>
//#include <mysql.h>
#include "config.h"

struct uir_node
{
	struct rb_node	node;
	uint64_t		key;		// 低位表示IP/或组, 高四位表示是IP或组
	uint64_t		parent;		// 上层IP
	uint32_t		tps[4];		// 0 ~ 121个类弄信息，按位运算
	int				changid;	// 改变ID
	uint8_t*		timerule;	// 时间规则，指向int[56], 表示一周内的秒数
	char*			whitelist;	// 指向白名单
	char*			blacklist;	// 指向黑名单
} __attribute__((aligned(sizeof(char*))));

struct rb_root		uir_root		= RB_ROOT;

/*
 * 初始化
 */
void uir_init(void)
{
	// 添加组
//	MYSQL		mysql;
	char		host[128]		= {0};
	char		user[128]		= {0};
	char		pwd[128]		= {0};
	char		db[128]			= {0};

//	mysql_init(&mysql);
	
//	if( !mysql_real_connect(&mysql, 
}

/*
 * 查找
 */
struct uir_node* _unsafe_uir_find(uint64_t key)
{
	struct rb_node*			node;
	struct uir_node*		item;
	int64_t					result;

	node = uir_root.rb_node;
	while(node)
	{
		item = rb_entry(node, struct uir_node, node);
		result = item->key - key;
		if(result < 0)
		{
			node = node->rb_left;
		}
		else if(result > 0)
		{
			node = node->rb_right;
		}
		else
		{
			return item;
		}
	}

	return NULL;
}

/*
 * 插入
 */
bool _unsafe_uir_insert(struct uir_node* item)
{
	struct rb_node		**new		= &(uir_root.rb_node);
	struct rb_node		*parent		= NULL;
	int64_t				result		= 0;
	struct uir_node		*this;

	while(*new)
	{
		this = rb_entry(*new, struct uir_node, node);
		result = item->key - this->key;
		parent = *new;
		if( result < 0 )
		{
			new = &((*new)->rb_left);
		}
		else if( result > 0 )
		{
			new = &((*new)->rb_right);
		}
		else
		{
			return false;
		}
	}

	rb_init_node(&(item->node));
	rb_link_node(&(item->node), parent, new);
	rb_insert_color(&(item->node), &uir_root);

	return true;
}

void _unsafe_uir_clear(struct rb_node** node)
{
	struct uir_node*		item;

	if(NULL == *node)
	{
		return;
	}

	_unsafe_uir_clear(&((*node)->rb_left));
	_unsafe_uir_clear(&((*node)->rb_right));

	item = rb_entry(*node, struct uir_node, node);
	free(item);
	*node = NULL;
}

bool str_in_array(const char* str, const char* array)
{
	const char*		p			= array;
	int				len			= strlen(str);

	for(; NULL != p; p = strchr(p, ';'))
	{
		while(';' == *p)
		{
			p++;
		}
		if(0 == strncmp(str, p, len))
		{
			if(0 == *(p + len) || ';' == *(p + len))
			{
				return true;
			}
		}
	};

	return false;
}
/*
 * 不安全的检测
 * 返回值: -1, 白名单, 0 放行, 1 类弄阻止, 2 用户黑名单
 */
int _unsafe_uir_checkurl(uint64_t key, const char* url, uint8_t tp)
{
	struct uir_node*		item;
	int						nret		= 0;

	item = _unsafe_uir_find(key);
	if(NULL == item)
	{
		return 0;
	}

	// 从父层判断结果
	if(0 != item->parent)
	{
		nret = _unsafe_uir_checkurl(item->parent, url, tp);
	}

	// 父层有判断出结果
	if(0 != nret)
	{
		return nret;
	}

	// 判断类弄
	if(tp > 127)
	{
		tp = 127;
	}
	if(0 != (item->tps[tp / 32] & (0x1 << (tp % 32))))
	{
		return 1;
	}

	// 判断白名单
	if(NULL != item->whitelist && str_in_array(url, item->whitelist))
	{
		return -1;
	}

	// 验证是不是黑名单
	if(NULL != item->blacklist && str_in_array(url, item->whitelist))
	{
		return 2;
	}

	return 0;
}
/*
 * 检测URL是否被阻止
 * 返回值: 0 放行, 1 类弄阻止, 2 用户黑名单
 */
int uir_checkurl(uint32_t ip, const char* url, uint8_t tp)
{
	int						nret		= 0;

	nret = _unsafe_uir_checkurl(IP_TO_KEY(ip), url, tp);
	if(-1 == nret)
	{
		nret = 0;
	}
	
	return nret;
}

bool _unsafe_uir_checktime(uint64_t key, struct tm* tm)
{
	struct uir_node*		item;
	bool					bret	= false;

	item = _unsafe_uir_find(key);
	if(NULL == item)
	{
		return false;
	}

	// 从父层判断结果
	if(0 != item->parent)
	{
		bret = _unsafe_uir_checktime(item->parent, tm);
	}
	if(false != bret)
	{
		return true;
	}

	// 从当前层判断结果
	if(0 != (item->timerule[tm->tm_wday * 8 + tm->tm_hour / 8] & (0x1 << (tm->tm_hour % 8))))
	{
		return true;
	}
	
	return false;
}
/* 
 * 检测时间是否到期
 * 返回true表示阻止, false 表示放行
 */
bool uir_checktime(uint32_t ip)
{
	struct tm		tm			= {0};
	bool			bret;
	time_t			t			= time(NULL);

	localtime_r(&t, &tm);

	bret = _unsafe_uir_checktime(IP_TO_KEY(ip), &tm);

	return bret;
}


